home *** CD-ROM | disk | FTP | other *** search
/ Programming a Multiplayer FPS in DirectX / Programming a Multiplayer FPS in DirectX (Companion CD).iso / DirectX / dxsdk_oct2004.exe / dxsdk.exe / Utilities / MView / gxu / adjoutline.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2004-09-30  |  24.0 KB  |  826 lines

  1. /*//////////////////////////////////////////////////////////////////////////////
  2. //
  3. // File: stripoutline.cpp
  4. //
  5. // Copyright (C) 1999 Microsoft Corporation. All Rights Reserved.
  6. //
  7. //
  8. //////////////////////////////////////////////////////////////////////////////*/
  9.  
  10. #include "pchgxu.h"
  11. #include "AdjOutline.h"
  12.  
  13. #define SKINNEDFVF D3DFVF_XYZB4|D3DFVF_TEX5|D3DFVF_TEXCOORDSIZE3(0)|D3DFVF_TEXCOORDSIZE4(1)|D3DFVF_TEXCOORDSIZE3(2)|D3DFVF_TEXCOORDSIZE4(3)|D3DFVF_TEXCOORDSIZE3(4)
  14. #define INDEXSKINNEDFVF D3DFVF_XYZB5|D3DFVF_TEX7|D3DFVF_TEXCOORDSIZE3(0)|D3DFVF_TEXCOORDSIZE4(1)|D3DFVF_TEXCOORDSIZE1(2)|D3DFVF_TEXCOORDSIZE3(3)|D3DFVF_TEXCOORDSIZE4(4)|D3DFVF_TEXCOORDSIZE1(5)|D3DFVF_TEXCOORDSIZE3(6)|D3DFVF_LASTBETA_D3DCOLOR
  15.  
  16. const int x_dwAdjOutlineColor = D3DCOLOR_XRGB(0, 255, 255);
  17.  
  18. CAdjacencyOutline::CAdjacencyOutline()
  19.     :m_cfvf(D3DFVF_XYZ),
  20.      m_bSkinning(FALSE),
  21.      m_bIndexSkinning(FALSE),
  22.      m_bHWVertexShaders(FALSE),
  23.      m_pVertexBuffer(NULL),
  24.      m_rgaeAttributeTable(NULL),
  25.      m_caeAttributeTable(0),
  26.      m_pDecl(NULL)
  27. {
  28. }
  29.  
  30. CAdjacencyOutline::~CAdjacencyOutline()
  31. {
  32.     delete m_rgaeAttributeTable;
  33.  
  34.     GXRELEASE(m_pVertexBuffer);
  35.     GXRELEASE(m_pDecl);
  36. }
  37.  
  38. void
  39. CAdjacencyOutline::AppendPoint
  40.     (
  41.     CD3DXCrackDecl1 &cdMesh, 
  42.     PUINT pwFace, 
  43.     PBYTE pvMeshPoints, 
  44.     PBYTE pvLinePoints, 
  45.     UINT &iCurPoint
  46.     )
  47. {
  48.     UINT iPoint;
  49.     PVOID pvPoint;
  50.     DWORD cFloats;
  51.     DWORD iFloat;
  52.     float *pfTemp;
  53.  
  54.     GXASSERT(m_cfvf.CWeights() == cdMesh.CWeights());
  55.  
  56.     cFloats = 3 /*vector*/ + cdMesh.CWeights();
  57.  
  58.     pfTemp = (float*)_alloca(cFloats * sizeof(float));
  59.     memset(pfTemp, 0, cFloats * sizeof(float));
  60.  
  61.     for (iPoint = 0; iPoint < 3; iPoint++)
  62.     {
  63.         pvPoint = cdMesh.GetArrayElem(pvMeshPoints, pwFace[iPoint]);
  64.         for (iFloat = 0; iFloat < cFloats; iFloat++)
  65.         {
  66.             pfTemp[iFloat] += ((float*)pvPoint)[iFloat];
  67.         }
  68.     }
  69.  
  70.     for (iFloat = 0; iFloat < cFloats; iFloat++)
  71.     {
  72.         pfTemp[iFloat] /= 3.0f;
  73.     }
  74.  
  75.     pvPoint = m_cfvf.GetArrayElem(pvLinePoints, iCurPoint);
  76.     memcpy(pvPoint, pfTemp, sizeof(float) * cFloats);
  77.  
  78.     iCurPoint += 1;
  79. }
  80.  
  81. void
  82. CAdjacencyOutline::AppendMidpoint
  83.     (
  84.     CD3DXCrackDecl1 &cdMesh, 
  85.     PUINT pwFace1, 
  86.     UINT iEdge, 
  87.     PBYTE pvMeshPoints, 
  88.     PBYTE pvLinePoints, 
  89.     UINT &iCurPoint
  90.     )
  91. {
  92.     PVOID pvPoint;
  93.     DWORD cFloats;
  94.     DWORD iFloat;
  95.     float *pfTemp;
  96.  
  97.     GXASSERT(m_cfvf.CWeights() == cdMesh.CWeights());
  98.  
  99.     cFloats = 3 /*vector*/ + cdMesh.CWeights();
  100.  
  101.     pfTemp = (float*)_alloca(cFloats * sizeof(float));
  102.  
  103.     pvPoint = cdMesh.GetArrayElem(pvMeshPoints, pwFace1[iEdge]);
  104.     for (iFloat = 0; iFloat < cFloats; iFloat++)
  105.     {
  106.         pfTemp[iFloat] = ((float*)pvPoint)[iFloat];
  107.     }
  108.  
  109.     pvPoint = cdMesh.GetArrayElem(pvMeshPoints, pwFace1[(iEdge+1)%3]);
  110.     for (iFloat = 0; iFloat < cFloats; iFloat++)
  111.     {
  112.         pfTemp[iFloat] += ((float*)pvPoint)[iFloat];
  113.  
  114.         pfTemp[iFloat] /= 2.0f;
  115.     }
  116.  
  117.     pvPoint = m_cfvf.GetArrayElem(pvLinePoints, iCurPoint);
  118.     memcpy(pvPoint, pfTemp, sizeof(float) * cFloats);
  119.  
  120.     iCurPoint += 1;
  121. }
  122.  
  123. void CopyWeights
  124.     (
  125.     float *pfWeightSrc,
  126.     DWORD cWeightsSrc,
  127.     float *pfWeightDest,
  128.     DWORD cWeightsDest
  129.     )
  130. {
  131.     float fSum;
  132.     DWORD iWeight;
  133.     float fWeight;
  134.  
  135.     // there should always be more dest weights than source
  136.     GXASSERT(cWeightsSrc < cWeightsDest);
  137.  
  138.     // first copy the weights that exist in the source
  139.     fSum = 0.0f;
  140.     for (iWeight = 0; iWeight < cWeightsSrc; iWeight++)
  141.     {
  142.         fWeight = pfWeightSrc[iWeight];
  143.         fSum += fWeight;
  144.  
  145.         pfWeightDest[iWeight] = fWeight;
  146.     }
  147.  
  148.     // now set the implied weight - always exists in dest
  149.     pfWeightDest[iWeight] = 1.0f - fSum;
  150.     iWeight += 1;
  151.  
  152.     // set any other weights that are unused to 0.0f
  153.     for (; iWeight < cWeightsDest; iWeight++)
  154.     {
  155.         pfWeightDest[iWeight] = 0.0f;
  156.     }
  157. }
  158.  
  159. void CopyIndexedWeights
  160.     (
  161.     float *pfWeightSrc,
  162.     DWORD cWeightsSrc,
  163.     float *pfWeightDest,
  164.     DWORD cWeightsDest
  165.     )
  166. {
  167.     float fSum;
  168.     DWORD iWeight;
  169.     float fWeight;
  170.  
  171.     // there should always be more dest weights than source
  172.     GXASSERT(cWeightsSrc < cWeightsDest);
  173.  
  174.     // first copy the weights that exist in the source
  175.     fSum = 0.0f;
  176.     for (iWeight = 0; iWeight < cWeightsSrc - 1; iWeight++)
  177.     {
  178.         fWeight = pfWeightSrc[iWeight];
  179.         fSum += fWeight;
  180.  
  181.         pfWeightDest[iWeight] = fWeight;
  182.     }
  183.  
  184.     // now set the implied weight - always exists in dest
  185.     pfWeightDest[iWeight] = 1.0f - fSum;
  186.     iWeight += 1;
  187.  
  188.     // set any other weights that are unused to 0.0f
  189.     for (; iWeight < cWeightsDest - 1; iWeight++)
  190.     {
  191.         pfWeightDest[iWeight] = 0.0f;
  192.     }
  193.  
  194.     // copy the indices straight from one to the other
  195.     memcpy(&pfWeightDest[cWeightsDest-1], &pfWeightSrc[cWeightsSrc-1], sizeof(DWORD));
  196. }
  197.  
  198. void
  199. CAdjacencyOutline::AppendPointSkinned
  200.     (
  201.     CD3DXCrackDecl1 &cdMesh, 
  202.     PUINT pwFace1, 
  203.     UINT iEdge, 
  204.     PBYTE pvMeshPoints, 
  205.     PBYTE pvLinePoints, 
  206.     UINT &iCurPoint
  207.     )
  208. {
  209.     PBYTE pvDestPoint;
  210.     PBYTE pvPoint;
  211.     D3DXVECTOR3 vAvg(1.0f/3.0f,1.0f/3.0f,1.0f/3.0f);
  212.  
  213.     pvDestPoint = m_cfvf.GetArrayElem(pvLinePoints, iCurPoint);
  214.  
  215.     // Point 0 - first point on edge shared with another triangle
  216.     pvPoint = cdMesh.GetArrayElem(pvMeshPoints, pwFace1[iEdge]);
  217.  
  218.     // first position goes in standard position spot
  219.     m_cfvf.SetPosition(pvDestPoint, cdMesh.PvGetPosition(pvPoint));
  220.  
  221.     // first set of weights go in standard spot - expand to standard length
  222.     CopyWeights(cdMesh.PfGetWeights(pvPoint), cdMesh.CWeights(), m_cfvf.PfGetWeights(pvDestPoint), m_cfvf.CWeights());
  223.  
  224.     // Point 1 - other point on edge shared with another triangle
  225.     pvPoint = cdMesh.GetArrayElem(pvMeshPoints, pwFace1[(iEdge+1)%3]);
  226.  
  227.     // second position goes in first texture coord
  228.     m_cfvf.SetTexCoord(pvDestPoint, 0, cdMesh.PvGetPosition(pvPoint));
  229.  
  230.     // second set of weights go in second texture coord- expand to standard length
  231.     CopyWeights(cdMesh.PfGetWeights(pvPoint), cdMesh.CWeights(), (float*)m_cfvf.PxyzwGetTexCoord(pvDestPoint, 1), m_cfvf.CWeights());
  232.  
  233.     // Point 2 - point NOT on edge shared with another triangle
  234.     pvPoint = cdMesh.GetArrayElem(pvMeshPoints, pwFace1[(iEdge+2)%3]);
  235.  
  236.     // third position goes in the third texture coordinate
  237.     m_cfvf.SetTexCoord(pvDestPoint, 2, cdMesh.PvGetPosition(pvPoint));
  238.  
  239.     // third set of weights go in fourth texture coord- expand to standard length
  240.     CopyWeights(cdMesh.PfGetWeights(pvPoint), cdMesh.CWeights(), (float*)m_cfvf.PxyzwGetTexCoord(pvDestPoint, 3), m_cfvf.CWeights());
  241.  
  242.  
  243.     // the third position should be added in
  244.     m_cfvf.SetTexCoord(pvDestPoint, 4, &vAvg);
  245.  
  246.     iCurPoint += 1;
  247. }
  248.  
  249. void
  250. CAdjacencyOutline::AppendMidpointSkinned
  251.     (
  252.     CD3DXCrackDecl1 &cdMesh, 
  253.     PUINT pwFace1, 
  254.     UINT iEdge, 
  255.     PBYTE pvMeshPoints, 
  256.     PBYTE pvLinePoints, 
  257.     UINT &iCurPoint
  258.     )
  259. {
  260.     PBYTE pvDestPoint;
  261.     D3DXVECTOR3 vMidPoint(0.5f, 0.5f, 0.0f);
  262.  
  263.     pvDestPoint = m_cfvf.GetArrayElem(pvLinePoints, iCurPoint);
  264.  
  265.     AppendPointSkinned(cdMesh, pwFace1, iEdge, pvMeshPoints, pvLinePoints, iCurPoint);
  266.  
  267.     // the third position should be ignored!
  268.     m_cfvf.SetTexCoord(pvDestPoint, 4, &vMidPoint);
  269. }
  270.  
  271. void
  272. CAdjacencyOutline::AppendPointIndexSkinned
  273.     (
  274.     CD3DXCrackDecl1 &cdMesh, 
  275.     PUINT pwFace1, 
  276.     UINT iEdge, 
  277.     PBYTE pvMeshPoints, 
  278.     PBYTE pvLinePoints, 
  279.     UINT &iCurPoint
  280.     )
  281. {
  282.     PBYTE pvDestPoint;
  283.     PBYTE pvPoint;
  284.     D3DXVECTOR3 vAvg(1.0f/3.0f,1.0f/3.0f,1.0f/3.0f);
  285.  
  286.     pvDestPoint = m_cfvf.GetArrayElem(pvLinePoints, iCurPoint);
  287.  
  288.     // Point 0 - first point on edge shared with another triangle
  289.     pvPoint = cdMesh.GetArrayElem(pvMeshPoints, pwFace1[iEdge]);
  290.  
  291.     // first position goes in standard position spot
  292.     m_cfvf.SetPosition(pvDestPoint, cdMesh.PvGetPosition(pvPoint));
  293.  
  294.     // first set of weights go in standard spot - expand to standard length
  295.     CopyIndexedWeights(cdMesh.PfGetWeights(pvPoint), cdMesh.CWeights() + 1, m_cfvf.PfGetWeights(pvDestPoint), m_cfvf.CWeights());
  296.     
  297.     // Point 1 - other point on edge shared with another triangle
  298.     pvPoint = cdMesh.GetArrayElem(pvMeshPoints, pwFace1[(iEdge+1)%3]);
  299.  
  300.     // second position goes in first texture coord
  301.     m_cfvf.SetTexCoord(pvDestPoint, 0, cdMesh.PvGetPosition(pvPoint));
  302.  
  303.     // second set of weights go in second texture coord- expand to standard length
  304.     CopyIndexedWeights(cdMesh.PfGetWeights(pvPoint), cdMesh.CWeights() + 1, (float*)m_cfvf.PxyzwGetTexCoord(pvDestPoint, 1), m_cfvf.CWeights());
  305.  
  306.     // Point 2 - point NOT on edge shared with another triangle
  307.     pvPoint = cdMesh.GetArrayElem(pvMeshPoints, pwFace1[(iEdge+2)%3]);
  308.  
  309.     // third position goes in the third texture coordinate
  310.     m_cfvf.SetTexCoord(pvDestPoint, 3, cdMesh.PvGetPosition(pvPoint));
  311.  
  312.     // third set of weights go in fourth texture coord- expand to standard length
  313.     CopyIndexedWeights(cdMesh.PfGetWeights(pvPoint), cdMesh.CWeights() + 1, (float*)m_cfvf.PxyzwGetTexCoord(pvDestPoint, 4), m_cfvf.CWeights());
  314.  
  315.  
  316.     // the third position should be added in
  317.     m_cfvf.SetTexCoord(pvDestPoint, 6, &vAvg);
  318.  
  319.     iCurPoint += 1;
  320. }
  321.  
  322. void
  323. CAdjacencyOutline::AppendMidpointIndexSkinned
  324.     (
  325.     CD3DXCrackDecl1 &cdMesh, 
  326.     PUINT pwFace1, 
  327.     UINT iEdge, 
  328.     PBYTE pvMeshPoints, 
  329.     PBYTE pvLinePoints, 
  330.     UINT &iCurPoint
  331.     )
  332. {
  333.     PBYTE pvDestPoint;
  334.     D3DXVECTOR3 vMidPoint(0.5f, 0.5f, 0.0f);
  335.  
  336.     pvDestPoint = m_cfvf.GetArrayElem(pvLinePoints, iCurPoint);
  337.  
  338.     AppendPointIndexSkinned(cdMesh, pwFace1, iEdge, pvMeshPoints, pvLinePoints, iCurPoint);
  339.  
  340.     // the third position should be ignored!
  341.     m_cfvf.SetTexCoord(pvDestPoint, 6, &vMidPoint);
  342. }
  343.  
  344. HRESULT
  345. CAdjacencyOutline::Init(ID3DXBaseMesh *ptmMesh, DWORD *rgdwNeighbors)
  346. {
  347.     HRESULT hr = S_OK;
  348.     UINT cFaces;
  349.     UINT iFace;
  350.     UINT cConnections;
  351.     UINT cPointsMax;
  352.     UINT iline;
  353.     PBYTE pvLinePoints = NULL;
  354.     PBYTE pvMeshPoints = NULL;
  355.     LPDIRECT3DVERTEXBUFFER9 pVBVertices = NULL;
  356.     LPDIRECT3DINDEXBUFFER9 pibFaces = NULL;
  357.     PUINT pdwFaceCur;
  358.     PUINT rgdwFaces = NULL;
  359.     CD3DXCrackDecl1 cdMesh;
  360.     PWORD rgwFaces = NULL;
  361.     bool b16BitMesh;
  362.     UINT iIndex;
  363.     UINT iPoint;
  364.     DWORD *pdwNeighbor;
  365.     UINT iCurPoint;
  366.     LPDIRECT3DDEVICE9 pDevice;
  367.     D3DXATTRIBUTERANGE *rgaeAttributeTableMesh = NULL;
  368.     DWORD iCurLineOffset;
  369.     DWORD iCurVertexOffset;
  370.     DWORD iFaceEnd;
  371.     DWORD iae;
  372.     DWORD dwFVFAdjVertices;
  373.     D3DCAPS9 Caps;
  374.     D3DVERTEXELEMENT9 pDecl[MAX_FVF_DECL_SIZE];
  375.     LPD3DVERTEXELEMENT9 pDeclCur;
  376.  
  377.     ptmMesh->GetDeclaration(pDecl);
  378.     cdMesh.SetDeclaration(pDecl);
  379.  
  380.     ptmMesh->GetDevice(&pDevice);
  381.     pDevice->Release();
  382.  
  383.     // is the mesh 16 bit?
  384.     b16BitMesh = !(ptmMesh->GetOptions() & D3DXMESH_32BIT);
  385.  
  386.     hr = CreateEmptyOutline();
  387.     if (FAILED(hr))
  388.         goto e_Exit;
  389.  
  390.     pDevice->GetDeviceCaps(&Caps);
  391.     m_bHWVertexShaders = Caps.VertexShaderVersion >= D3DVS_VERSION(1,1);
  392.  
  393.     if (cdMesh.CWeights() > 0)
  394.     {
  395.         m_bSkinning = TRUE;
  396.  
  397.         if (cdMesh.BIndexedWeights())
  398.         {
  399.             dwFVFAdjVertices = INDEXSKINNEDFVF;
  400.             m_bIndexSkinning = TRUE;
  401.         }
  402.         else
  403.         {
  404.             dwFVFAdjVertices = SKINNEDFVF;
  405.             m_bIndexSkinning = FALSE;
  406.         }
  407.     }
  408.     else
  409.     {
  410.         dwFVFAdjVertices = D3DFVF_XYZ;
  411.         m_bSkinning = FALSE;
  412.         m_bIndexSkinning = FALSE;
  413.     }
  414.     m_cfvf = DXCrackFVF(dwFVFAdjVertices);
  415.  
  416.     if (rgdwNeighbors == NULL)
  417.         goto e_Exit;
  418.  
  419.     hr = ptmMesh->GetAttributeTable(NULL, &m_caeAttributeTable);
  420.     if (FAILED(hr))
  421.         goto e_Exit;
  422.  
  423.     if (m_caeAttributeTable == 0)
  424.     {
  425.         // not attribute sorted!  just return for now
  426.         goto e_Exit;
  427.     }
  428.  
  429.     rgaeAttributeTableMesh = new D3DXATTRIBUTERANGE[m_caeAttributeTable];
  430.     m_rgaeAttributeTable = new D3DXATTRIBUTERANGE[m_caeAttributeTable];
  431.     if ((rgaeAttributeTableMesh == NULL) || (rgaeAttributeTableMesh == NULL))
  432.     {
  433.         hr = E_OUTOFMEMORY;
  434.         goto e_Exit;
  435.     }
  436.  
  437.     hr = ptmMesh->GetAttributeTable(rgaeAttributeTableMesh, NULL);
  438.     if (FAILED(hr))
  439.         goto e_Exit;
  440.  
  441.     cFaces = rgaeAttributeTableMesh[m_caeAttributeTable-1].FaceStart + rgaeAttributeTableMesh[m_caeAttributeTable-1].FaceCount;
  442.  
  443.     if (b16BitMesh)
  444.     {
  445.         // allocate a temporary, so that the follow code
  446.         //   can work on just 32bit indices
  447.         rgdwFaces = new UINT[cFaces*3];
  448.         if (rgdwFaces == NULL)
  449.         {
  450.             hr = E_OUTOFMEMORY;
  451.             goto e_Exit;
  452.         }
  453.  
  454.         // get the index buffer
  455.         hr = ptmMesh->GetIndexBuffer(&pibFaces);
  456.         if (FAILED(hr))
  457.             goto e_Exit;
  458.  
  459.         hr = pibFaces->Lock(0,0, (PVOID*)&rgwFaces, D3DLOCK_NOSYSLOCK );
  460.         if (FAILED(hr))
  461.             goto e_Exit;
  462.  
  463.         // UpConvert from 16 bit to 32 bit
  464.         for (iIndex = 0; iIndex < cFaces * 3; iIndex++)
  465.         {
  466.             if (rgwFaces[iIndex] != UNUSED16)
  467.                 rgdwFaces[iIndex] = rgwFaces[iIndex];
  468.             else
  469.                 rgdwFaces[iIndex] = UNUSED32;
  470.         }
  471.     }
  472.     else
  473.     {
  474.         // get the index buffer
  475.         hr = ptmMesh->GetIndexBuffer(&pibFaces);
  476.         if (FAILED(hr))
  477.             goto e_Exit;
  478.  
  479.         hr = pibFaces->Lock(0,0, (PVOID*)&rgdwFaces, D3DLOCK_NOSYSLOCK );
  480.         if (FAILED(hr))
  481.             goto e_Exit;
  482.     }
  483.  
  484.     // first count the number of links
  485.     cConnections = 0;
  486.     iCurLineOffset = 0;
  487.     iCurVertexOffset = 0;
  488.     for (iae = 0; iae < m_caeAttributeTable; iae++)
  489.     {
  490.         m_rgaeAttributeTable[iae].AttribId = rgaeAttributeTableMesh[iae].AttribId;
  491.  
  492.         // initialize line counts
  493.         m_rgaeAttributeTable[iae].FaceStart = iCurLineOffset;
  494.         m_rgaeAttributeTable[iae].FaceCount = 0;
  495.  
  496.         iFaceEnd = rgaeAttributeTableMesh[iae].FaceStart + rgaeAttributeTableMesh[iae].FaceCount;
  497.         for (iFace = rgaeAttributeTableMesh[iae].FaceStart; iFace < iFaceEnd; iFace++)
  498.         {
  499.             for (iPoint = 0; iPoint < 3; iPoint++)
  500.             {
  501.                 if (rgdwNeighbors[iFace*3 + iPoint] != UNUSED32)
  502.                 {
  503.                     cConnections += 1;
  504.                     m_rgaeAttributeTable[iae].FaceCount += 1;
  505.                 }
  506.             }
  507.         }
  508.  
  509.         m_rgaeAttributeTable[iae].VertexStart = iCurVertexOffset;
  510.         m_rgaeAttributeTable[iae].VertexCount = m_rgaeAttributeTable[iae].FaceCount*2;
  511.  
  512.         iCurLineOffset += m_rgaeAttributeTable[iae].FaceCount;
  513.         iCurVertexOffset += m_rgaeAttributeTable[iae].VertexCount;
  514.     }
  515.  
  516.     // should be even, otherwise the adjacency info is definitely incorrect
  517.     GXASSERT((cConnections & 1) == 0);
  518.     cPointsMax = cConnections * 2;
  519.  
  520.     // UNDONE UNDONE, need to handle large line lists
  521.     //if (cConnections >= UNUSED16)
  522.       //  goto e_Exit;
  523.  
  524.     if (cPointsMax == 0)
  525.         goto e_Exit;
  526.  
  527.     hr = pDevice->CreateVertexBuffer(m_cfvf.m_cBytesPerVertex * cPointsMax, 
  528.                         D3DUSAGE_WRITEONLY|(m_bHWVertexShaders ? 0:D3DUSAGE_SOFTWAREPROCESSING), 
  529.                         m_cfvf.m_dwFVF, D3DPOOL_MANAGED, &m_pVertexBuffer, NULL);
  530.     if (FAILED(hr))
  531.         goto e_Exit;
  532.  
  533.     m_pVertexBuffer->Lock(0, 0, (PVOID*)&pvLinePoints, 0);
  534.  
  535.     hr = ptmMesh->GetVertexBuffer(&pVBVertices);
  536.     if (FAILED(hr))
  537.         goto e_Exit;
  538.  
  539.     hr = pVBVertices->Lock(0,0, (PVOID*)&pvMeshPoints, D3DLOCK_NOSYSLOCK );
  540.     if (FAILED(hr))
  541.         goto e_Exit;
  542.  
  543.     iCurPoint = 0;
  544.     iline = 0;
  545.     for (iae = 0; iae < m_caeAttributeTable; iae++)
  546.     {
  547.         iFaceEnd = rgaeAttributeTableMesh[iae].FaceStart + rgaeAttributeTableMesh[iae].FaceCount;
  548.         for (iFace = rgaeAttributeTableMesh[iae].FaceStart; iFace < iFaceEnd; iFace++)
  549.         {
  550.             pdwNeighbor = &rgdwNeighbors[iFace * 3];
  551.             pdwFaceCur = &rgdwFaces[iFace * 3];
  552.             if (pdwFaceCur[0] == UNUSED32)
  553.                 break;
  554.  
  555.             for (iPoint = 0; iPoint < 3; iPoint++)
  556.             {
  557.                 if (pdwNeighbor[iPoint] != UNUSED32)
  558.                 {
  559.                     if (m_bIndexSkinning)
  560.                     {
  561.                         AppendPointIndexSkinned(cdMesh, pdwFaceCur, iPoint, pvMeshPoints, pvLinePoints, iCurPoint);
  562.  
  563.                         AppendMidpointIndexSkinned(cdMesh, pdwFaceCur, iPoint, pvMeshPoints, pvLinePoints, iCurPoint);
  564.                     }
  565.                     else if (m_bSkinning)
  566.                     {
  567.                         AppendPointSkinned(cdMesh, pdwFaceCur, iPoint, pvMeshPoints, pvLinePoints, iCurPoint);
  568.  
  569.                         AppendMidpointSkinned(cdMesh, pdwFaceCur, iPoint, pvMeshPoints, pvLinePoints, iCurPoint);
  570.                     }
  571.                     else
  572.                     {
  573.                         AppendPoint(cdMesh, pdwFaceCur, pvMeshPoints, pvLinePoints, iCurPoint);
  574.  
  575.                         AppendMidpoint(cdMesh, pdwFaceCur, iPoint, pvMeshPoints, pvLinePoints, iCurPoint);
  576.                     }
  577.  
  578.                     iline += 1;
  579.                 }
  580.             }
  581.         }
  582.     }
  583.  
  584.     // create a vertex declaration, so that we can have D3DCOLOR instead of UBYTE4 for the matrix indices 
  585.     hr = D3DXDeclaratorFromFVF(m_cfvf.m_dwFVF, pDecl);
  586.     if (FAILED(hr))
  587.         goto e_Exit;
  588.  
  589.     // swap the type of any blendilndices to D3DCOLOR
  590.     pDeclCur = pDecl;
  591.     while (pDeclCur->Stream != 0xff)
  592.     {
  593.         if ((pDeclCur->Usage == D3DDECLUSAGE_BLENDINDICES) || (pDeclCur->Type == D3DDECLTYPE_FLOAT1))
  594.         {
  595.             //pDeclCur->Type = D3DDECLTYPE_UBYTE4;
  596.             pDeclCur->Type = D3DDECLTYPE_D3DCOLOR;
  597.         }
  598.         pDeclCur++;
  599.     }
  600.  
  601.     GXRELEASE(m_pDecl);
  602.     hr = pDevice->CreateVertexDeclaration(pDecl, &m_pDecl);
  603.     if (FAILED(hr))
  604.         goto e_Exit;
  605.  
  606.  
  607. e_Exit:
  608.     if (pvLinePoints != NULL)
  609.     {
  610.         m_pVertexBuffer->Unlock();
  611.     }
  612.  
  613.     // if a 16 bit mesh, then rgdwFaces is a temporary array
  614.     if (b16BitMesh)
  615.     {
  616.         delete []rgdwFaces;
  617.  
  618.         if (rgwFaces != NULL)
  619.         {
  620.             pibFaces->Unlock();
  621.         }
  622.     }
  623.     else
  624.     {
  625.         if (rgdwFaces != NULL)
  626.         {
  627.             pibFaces->Unlock();
  628.         }
  629.     }
  630.     GXRELEASE(pibFaces);
  631.  
  632.     if (pvMeshPoints)
  633.     {
  634.         GXASSERT(pVBVertices != NULL);
  635.         pVBVertices->Unlock();
  636.     }
  637.     GXRELEASE(pVBVertices);
  638.  
  639.     delete []rgaeAttributeTableMesh;
  640.  
  641.     return hr;
  642. }
  643.  
  644. // matrix names for variables in FX file
  645. static const char *x_rgszMatrix[] =
  646. {
  647.  "mWd1", "mWd2", "mWd3", "mWd4", "mWd5", "mWd6", "mWd7", "mWd8", "mWd9",
  648.  "mWd10", "mWd11", "mWd12", "mWd13", "mWd14", "mWd15", "mWd16", "mWd17", "mWd18", "mWd19",
  649.  "mWd20", "mWd21", "mWd22", "mWd23", "mWd24", "mWd25", "mWd26", "mWd27", "mWd28"
  650. };
  651.  
  652. HRESULT
  653. CAdjacencyOutline::Draw
  654.     (
  655.     LPDIRECT3DDEVICE9 pDevice, 
  656.     DWORD iAttrib, 
  657.     LPD3DXEFFECT pfxSkinnedAdjacency, 
  658.     LPD3DXEFFECT pfxColor, 
  659.     DWORD dwColor,
  660.     D3DXMATRIX *rgmIndexedMatrices,
  661.     DWORD cIndexedMatrices
  662.     )
  663. {
  664.     HRESULT hr;
  665.     LPD3DXEFFECT pfxCurrent;
  666.     DWORD dwFVF;
  667.     UINT iPass;
  668.     UINT cPasses;
  669.     DWORD cBytesPerVertex;
  670.     D3DXMATRIX matWorld;
  671.     D3DXMATRIX matView;
  672.     D3DXMATRIX matProj;
  673.     D3DXMATRIX matTot;
  674.     D3DXCOLOR vClr(dwColor);
  675.     DWORD cLines;
  676.     DWORD cLinesCur;
  677.     DWORD iVertexStart;
  678.     BOOL  dwSoftwareMode;
  679.     BOOL bChangedSWMode = FALSE;
  680.     DWORD iMatrix;
  681.     DWORD iSubset;
  682.  
  683.     if (m_bSkinning)
  684.     {
  685.         if (!m_bIndexSkinning)
  686.         {
  687.             // non-indexed skinning setup
  688.             pfxCurrent = pfxSkinnedAdjacency;
  689.             pfxSkinnedAdjacency->SetTechnique(pfxSkinnedAdjacency->GetTechnique(0));
  690.  
  691.             pDevice->GetTransform(D3DTS_VIEW,&matView);
  692.             pDevice->GetTransform(D3DTS_PROJECTION,&matProj);
  693.             pDevice->GetTransform(D3DTS_WORLD,&matWorld);
  694.  
  695.             D3DXMatrixMultiply(&matTot,&matView,&matProj);
  696.             pfxSkinnedAdjacency->SetMatrix("mTot", &matTot);                       
  697.  
  698.             pDevice->GetTransform(D3DTS_WORLD,&matWorld);
  699.             pfxSkinnedAdjacency->SetMatrix("mWd1", &matWorld);                       
  700.  
  701.             pDevice->GetTransform(D3DTS_WORLD1,&matWorld);
  702.             pfxSkinnedAdjacency->SetMatrix("mWd2", &matWorld);                       
  703.  
  704.             pDevice->GetTransform(D3DTS_WORLD2,&matWorld);
  705.             pfxSkinnedAdjacency->SetMatrix("mWd3", &matWorld);                       
  706.  
  707.             pDevice->GetTransform(D3DTS_WORLD3,&matWorld);
  708.             pfxSkinnedAdjacency->SetMatrix("mWd4", &matWorld);        
  709.         }        
  710.         else  // indexed skinning setup
  711.         {
  712.             pfxCurrent = pfxSkinnedAdjacency;
  713.             pfxSkinnedAdjacency->SetTechnique(pfxSkinnedAdjacency->GetTechnique(1));
  714.  
  715.             pDevice->GetTransform(D3DTS_VIEW,&matView);
  716.             pDevice->GetTransform(D3DTS_PROJECTION,&matProj);
  717.  
  718.             D3DXMatrixMultiply(&matTot,&matView,&matProj);
  719.             pfxSkinnedAdjacency->SetMatrix("mTot", &matTot);                       
  720.  
  721.             for (iMatrix = 0; iMatrix < cIndexedMatrices; iMatrix++)
  722.             {
  723.                 pfxSkinnedAdjacency->SetMatrix(x_rgszMatrix[iMatrix], &rgmIndexedMatrices[iMatrix]);
  724.             }
  725.  
  726.             pfxSkinnedAdjacency->SetMatrixArray("mWorlds", rgmIndexedMatrices, cIndexedMatrices);
  727.         }
  728.  
  729.         pfxSkinnedAdjacency->SetVector("vClr", (D3DXVECTOR4*)&vClr);                       
  730.  
  731.         dwSoftwareMode = pDevice->GetSoftwareVertexProcessing();
  732.         if (!m_bHWVertexShaders)
  733.         {
  734.             bChangedSWMode = TRUE;
  735.             pDevice->SetSoftwareVertexProcessing(TRUE);
  736.         }
  737.         // if in the wrong mode, then switch
  738.         else if (dwSoftwareMode && m_bHWVertexShaders)
  739.         {
  740.             bChangedSWMode = TRUE;
  741.             pDevice->SetSoftwareVertexProcessing(FALSE);
  742.         }
  743.     }
  744.     else
  745.     {
  746.         pfxCurrent = pfxColor;
  747.         pfxCurrent->SetVector("vClr", (D3DXVECTOR4*)&vClr);                       
  748.     }
  749.  
  750.  
  751.     if ((iAttrib < m_caeAttributeTable) && (m_rgaeAttributeTable[iAttrib].AttribId == iAttrib))
  752.     {
  753.         iSubset = iAttrib;
  754.     }
  755.     else
  756.     {
  757.         // look for the correct attribute table entry to draw
  758.         for (iSubset = 0; iSubset < m_caeAttributeTable; iSubset++)
  759.         {
  760.             if (m_rgaeAttributeTable[iSubset].AttribId == iAttrib)
  761.             {
  762.                 break;
  763.             }
  764.         }
  765.     }
  766.  
  767.     if (iSubset < m_caeAttributeTable)
  768.     {
  769.         if (m_rgaeAttributeTable[iSubset].FaceCount > 0)
  770.         {
  771.             pfxCurrent->Begin(&cPasses, 0);
  772.  
  773.             for (iPass = 0; iPass < cPasses; iPass++)
  774.             {
  775.                 pDevice->SetVertexDeclaration(m_pDecl);
  776.  
  777.                 pfxCurrent->BeginPass(iPass);
  778.  
  779.                 pDevice->SetStreamSource(0, m_pVertexBuffer, 0, m_cfvf.m_cBytesPerVertex);
  780.  
  781.                 iVertexStart = m_rgaeAttributeTable[iSubset].VertexStart;
  782.                 cLines = m_rgaeAttributeTable[iSubset].VertexCount / 2;
  783.  
  784.                 while (cLines > 0)
  785.                 {
  786.                     cLinesCur = min(cLines, (0xffff / 2));
  787.  
  788.                     hr = pDevice->DrawPrimitive(D3DPT_LINELIST, 
  789.                                                  iVertexStart, 
  790.                                                  cLinesCur);
  791.                     if (FAILED(hr))
  792.                         return hr;
  793.  
  794.                     iVertexStart += cLinesCur * 2;
  795.                     cLines -= cLinesCur;
  796.                 }
  797.              
  798.                 pfxCurrent->EndPass();
  799.             }
  800.  
  801.             pfxCurrent->End();
  802.  
  803.  
  804.         }
  805.     }
  806.  
  807.     if (bChangedSWMode)
  808.     {
  809.         pDevice->SetSoftwareVertexProcessing(dwSoftwareMode);
  810.     }
  811.  
  812.     return S_OK;
  813. }
  814.  
  815. HRESULT
  816. CAdjacencyOutline::CreateEmptyOutline()
  817. {
  818.     GXRELEASE(m_pVertexBuffer);
  819.     delete []m_rgaeAttributeTable;
  820.     m_rgaeAttributeTable = NULL;
  821.  
  822.     m_caeAttributeTable = 0;
  823.  
  824.     return S_OK;
  825. }
  826.